from typing import *
import cv2, numpy as np
import ramda as R
from tasks import TaskUnit

def make_hash(img) -> str:
    avg_np = np.mean(img)
    bitarr = np.where(img>avg_np, 1, 0)
    binlines = R.map((lambda a:''.join(R.map(str, a))), bitarr)
    hexs = R.map((lambda a:f"{int(a,base=2):X}"), binlines)
    return ''.join(hexs)

class LuImg(TaskUnit):
    def __init__(me, hash_size:int=32):
        me.__hashs = dict()
        me.__dup_groups = dict()
        me.__HASH_SIZE = hash_size

    def reset(me) -> None:
        me.__hashs = dict()
        me.__dup_groups = dict()

    def add(me, path:str) -> None:
        img_a = cv2.imdecode(np.fromfile(path, dtype=np.uint8), -1)
        w = img_a.shape[0]
        h = img_a.shape[1]
        size_min = min(w, h)
        img_b = img_a[0:size_min, 0:size_min]
        img_c = cv2.resize(img_b, (me.__HASH_SIZE, me.__HASH_SIZE))
        img_d = cv2.cvtColor(img_c, cv2.COLOR_BGR2GRAY)
        hash = make_hash(img_d)
        if hash in me.__hashs:
            first_dup_name = me.__hashs[hash]
            if not first_dup_name in me.__dup_groups:
                me.__dup_groups[first_dup_name] = set()
                me.__dup_groups[first_dup_name].add(first_dup_name)
            me.__dup_groups[first_dup_name].add(path)
        else:
            me.__hashs[hash] = path

    def result_groups(me) -> List:
        groups = list()
        for names in me.__dup_groups.values():
            groups.append(list(names))
        return groups

